package indigo.ueditor.handler;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import com.google.common.collect.Maps;
import com.google.common.io.Files;

import indigo.ueditor.PathPatternResolver;
import indigo.ueditor.UEditorException;
import indigo.ueditor.UEditorFileManager;
import indigo.ueditor.UEditorHandler;
import indigo.ueditor.UEditorState;

public class MultipartUploadHandler implements UEditorHandler {
	private final String name;
	private final UEditorFileManager fileManager;
	private final String savePathPattern;
	private final long maxSize;
	private final Set<String> allowedSuffixes;

	public MultipartUploadHandler(String name, UEditorFileManager fileManager,
			String savePathPattern, long maxSize, Set<String> allowedSuffixes) {
		this.name = name;
		this.fileManager = fileManager;
		this.savePathPattern = savePathPattern;
		this.maxSize = maxSize;
		this.allowedSuffixes = allowedSuffixes;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public Object handle(HttpServletRequest request) {
		if (!(request instanceof MultipartRequest)) {
			throw new UEditorException(UEditorState.NOT_MULTIPART_CONTENT);
		}

		Map<String, MultipartFile> fileMap = ((MultipartRequest) request).getFileMap();
		if (fileMap.isEmpty()) {
			throw new UEditorException(UEditorState.NOTFOUND_UPLOAD_DATA);
		}

		MultipartFile multipartFile = fileMap.values().iterator().next();
		String fileName = multipartFile.getOriginalFilename();
		String fileBaseName = Files.getNameWithoutExtension(fileName);
		String fileExtension = Files.getFileExtension(fileName);
		String fileSuffix = fileExtension.isEmpty() ? "" : "." + fileExtension;
		if (!allowedSuffixes.contains(fileSuffix)) {
			throw new UEditorException(UEditorState.NOT_ALLOW_FILE_TYPE);
		}

		PathPatternResolver resolver = new PathPatternResolver();
		resolver.putVariable("filename", santizeTextInPath(fileBaseName));
		String savePath = resolver.resolve(savePathPattern) + fileSuffix;

		try (InputStream is = multipartFile.getInputStream()) {
			fileManager.createFile(savePath, is, maxSize);
		} catch (IOException e) {
			throw new UEditorException(UEditorState.IO_ERROR, e);
		}

		Map<String, Object> resultMap = Maps.newHashMap();
		resultMap.put("state", UEditorState.SUCCESS.getMessage());
		resultMap.put("url", savePath);
		resultMap.put("type", fileSuffix);
		resultMap.put("original", fileName);
		return resultMap;
	}

	private String santizeTextInPath(String text) {
		return text.replace("$", "\\$").replaceAll("[\\/:*?\"<>|]", "");
	}
}
